14. Exercise: Error Handling with RecyclerView

L8 25 Error Handling With RecyclerView SC

Erratum

At timestamp 00:35 in the video above, in OverviewViewModel.kt file, the definition of the getMarsRealEstateProperties() function has been updated due to deprecated Retrofit 2 Call callbacks. Consider the new definition of the getMarsRealEstateProperties() function as mentioned in the instructions below, or alternatively, you can check out the relevant solution branch of the Git repo.

Now it's your turn!

In this exercise you'll add error handling and status messages to make your app more robust. If you want to start at this step, you can download the code from: Step.06-Exercise-Error-Handling-with-RecyclerView. You will find plenty of //TODO comments in the exercise code to help you out.

  1. In OverviewViewModel, create a MarsApiStatus enum with LOADING, ERROR, DONE states.

    Note: We created it outside of the class, but it can go either place.

enum class MarsApiStatus { LOADING, ERROR, DONE }


  1. Change _status type from String to MarsApiStatus.
    private val _status = MutableLiveData<MarsApiStatus>()
    val status: LiveData<MarsApiStatus>
       get() = _status



  1. In getMarsRealEstateProperties(), using the enums defined above, set _status value to LOADING, DONE, or ERROR. In the error case, clear the properties LiveData by setting it to a new empty ArrayList:
    private fun getMarsRealEstateProperties() {
        viewModelScope.launch {
            _status.value = MarsApiStatus.LOADING
            try {
                _properties.value = MarsApi.retrofitService.getProperties(filter.value)
                _status.value = MarsApiStatus.DONE
            } catch (e: Exception) {
                _status.value = MarsApiStatus.ERROR
                _properties.value = ArrayList()
            }
        }
    }


  1. In BindingAdapters.kt, add a binding adapter to show MarsApiStatus in the ImageView, and set the view's visibility depending on the status value:

    @BindingAdapter("marsApiStatus")
    fun bindStatus(statusImageView: ImageView, status: MarsApiStatus?) {
       when (status) {
           MarsApiStatus.LOADING -> {
                statusImageView.visibility = View.VISIBLE
                statusImageView.setImageResource(R.drawable.loading_animation)
           }
           MarsApiStatus.ERROR -> {
                statusImageView.visibility = View.VISIBLE
                statusImageView.setImageResource(R.drawable.ic_connection_error)
           }
           MarsApiStatus.DONE -> {
                statusImageView.visibility = View.GONE
           }
       }
    } 


  2. In fragment_overview, add a status_image ImageView to the ConstraintLayout.

    Set its width and height to wrap_content, and assign it the same layout constraints as the RecyclerView.

    Also include an attribute to bind the marsApiStatus binding adapter to viewModel.status:

     <ImageView
        android:id="@+id/status_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:marsApiStatus="@{viewModel.status}" />


If you get stuck, go back and watch the video again. Once you’re done, you can check your solution against the solution we’ve provided here: Step.06-Solution-Error-Handling-with-RecyclerView, or using this git diff.

Task Description:

Complete the tasks below to add error handling to your network calls.

Task List:

Task Feedback:

Great job!